home *** CD-ROM | disk | FTP | other *** search
/ QuickTime 2.0 Developer Kit / QuickTime 2.0 Developer Kit.iso / mac / MAC / Programming Stuff / Documentation / develop / develop Issue 20 / develop 20 code / Sound Components / MewLaw / MewLaw.c next >
Encoding:
C/C++ Source or Header  |  1994-10-14  |  30.5 KB  |  806 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        MewLaw.c
  3.  
  4.     Contains:    Sample sound decompression component to convert
  5.                 µLaw-encoded data into 16-bit linear samples
  6.  
  7.     Written by:    Kip Olson
  8.  
  9.     Copyright:    © 1994 by Apple Computer, Inc.
  10. */
  11.  
  12. #include <Memory.h>
  13. #include <Errors.h>
  14. #include <SoundInput.h>
  15. #include <Components.h>
  16. #include <GestaltEqu.h>
  17.  
  18. #include "Sound.h"
  19. #include "SoundComponents.h"
  20.  
  21. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  22. // Constants
  23. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  24.  
  25. #define kDelegateComponentCall            ((ComponentRoutine) -1L)    // flag that selector should be delegated instead of called
  26.  
  27. #define kMewLawVersion                    0x00010000        // version for this sound component
  28. #define kRequiredSndMgrMajorRev            3                // Sound Manager version required to run this component
  29.  
  30. #define kOutputSampleFormat                'twos'            // output sample format
  31. #define kOutputSampleSize                16                // output sample size
  32. #define kMaxOutputSamples                1024            // max no. samples in output buffer
  33.  
  34. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  35. // Data Structures
  36. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  37.  
  38. /* Sound component globals */
  39.  
  40. typedef struct {
  41.  
  42. // these are general purpose variables that every sound component will need
  43.     ComponentInstance        sourceComponent;            // component to call when we need more data
  44.     SoundComponentDataPtr    sourceDataPtr;                // pointer to source data structure
  45.     SoundComponentData        thisComponent;                // description of this component's output
  46.     Handle                    globalsHandle;                // handle to component globals
  47.     short                    outputFrames;                // max no. frames in output buffer
  48.     short                    outputSamples;                // max no. samples in output buffer
  49.     CompressionInfo            compInfo;                    // info about compressor
  50.     Boolean                    reverse;                    // true if data should be played back in reverse
  51.     Boolean                    pad1;
  52.     short                    buffer[kMaxOutputSamples * 2];    // room for 16-bit, stereo samples
  53. } GlobalsRecord, *GlobalsPtr;
  54.  
  55. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  56. // Prototypes
  57. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  58.  
  59. #ifdef THINK_C
  60. pascal ComponentResult    main(ComponentParameters *params, GlobalsPtr globals);
  61. #else
  62. pascal ComponentResult    MewLaw(ComponentParameters *params, GlobalsPtr globals);
  63. #endif
  64.  
  65. ComponentRoutine        GetComponentRoutine(short selector);
  66. pascal ComponentResult    __ComponentRegister(void *unused1);
  67. pascal ComponentResult    __ComponentVersion(void *unused1);
  68. pascal ComponentResult    __ComponentCanDo(void *unused1, short selector);
  69. pascal ComponentResult    __ComponentOpen(void *unused1, ComponentInstance self);
  70. pascal ComponentResult    __ComponentClose(GlobalsPtr globals, ComponentInstance self);
  71. pascal ComponentResult    __SetSource(GlobalsPtr globals, SoundSource sourceID, ComponentInstance source);
  72. pascal ComponentResult    __SetOutput(GlobalsPtr globals, SoundComponentDataPtr requested, 
  73.                             SoundComponentDataPtr *actual);
  74. pascal ComponentResult    __GetInfo(GlobalsPtr globals, SoundSource sourceID, OSType selector, void *infoPtr);
  75. pascal ComponentResult    __StopSource(GlobalsPtr globals, short count, SoundSource *sources);
  76. pascal ComponentResult    __PlaySourceBuffer(GlobalsPtr globals, SoundSource sourceID, SoundParamBlockPtr pb, 
  77.                             long actions);
  78. pascal ComponentResult    __GetSourceData(GlobalsPtr globals, SoundComponentDataPtr *resultDataPtr);
  79. ComponentResult            PrimeSource(GlobalsPtr globals);
  80. void                    InitializeDecompressor(GlobalsPtr globals);
  81. void                    GetCompressorInfo(CompressionInfoPtr cp);
  82. void                    DecompressULaw(Byte *inbuf, short *outbuf, unsigned long framesToConvert, 
  83.                             unsigned long numChannels, unsigned long whichChannel);
  84.  
  85. // Think C will use A4 to reference globals and tables, so we need to
  86. // save, setup and restore A4 in our main loop. The following are some
  87. // handy inlines for dealing with A4.
  88.  
  89. #ifdef THINK_C
  90.  
  91. #pragma parameter  SetRegisterA4(__A0)
  92. void  SetRegisterA4(void *a4) = { 0x2848 };    /* move.l    a0,a4 */
  93. void* GetRegisterA4(void) = { 0x200C };        /* move.l    a4,d0 */
  94.  
  95. #endif
  96.  
  97. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  98. // Main Component Entry Point
  99. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  100.  
  101. /*    =======================================================================================
  102.     MewLaw
  103.  
  104.     The function of this routine is to dispatch to the appropriate component method. It first
  105.     calls finds the address of the method to dispatch to using the selector provided in the
  106.     what field of the parameter block. If the address is -1L, then this selector should
  107.     be delegated. If the address is nil, this selector is not supported.
  108.     ======================================================================================= */
  109.  
  110. #ifdef THINK_C
  111. pascal ComponentResult main(ComponentParameters *params, GlobalsPtr globals)
  112. #else
  113. pascal ComponentResult MewLaw(ComponentParameters *params, GlobalsPtr globals)
  114. #endif
  115. {
  116.     ComponentRoutine    theRtn;
  117.     ComponentResult        result;
  118.  
  119. #ifdef THINK_C
  120.     void    *savedA4;
  121.     
  122.     savedA4 = GetRegisterA4();
  123.     SetRegisterA4(main);
  124. #endif
  125.  
  126.     theRtn = GetComponentRoutine(params->what);                // get address of component routine
  127.  
  128.     if (theRtn == nil)                                        // selector not implemented
  129.         result = badComponentSelector;
  130.     else if (theRtn == kDelegateComponentCall)                // selector should be delegated
  131.         result = DelegateComponentCall(params, globals->sourceComponent);
  132.     else
  133.         result = CallComponentFunctionWithStorage((Handle) globals, params, (ComponentFunctionUPP) theRtn);
  134.  
  135. #ifdef THINK_C
  136.     SetRegisterA4(savedA4);
  137. #endif
  138.  
  139.     return (result);
  140.  
  141. }
  142.  
  143. /*    =======================================================================================
  144.     GetComponentRoutine
  145.  
  146.     The function of this routine is to return the address of the appropriate component method.
  147.     To do this, the routine must deal with 3 selector ranges:
  148.  
  149.     -5 to -1    These are the standard Component Manager selectors that all components
  150.                 must share. Refer to the Component Manager documentation for more info.
  151.  
  152.     0 to 255    These selectors cannot be delegated. If the sound component does not implement
  153.                 one of these selectors, it should return the badComponentSelector error.
  154.  
  155.     256 to ∞    These selectors should be delegated. If the sound component does not implement
  156.                 one of these selectors, it should use DelegateComponentCall() to pass
  157.                 this selector on up the chain. If the sound component does implement this
  158.                 selector, it should first delegate the selector, then perform the function.
  159.     ======================================================================================= */
  160.  
  161. ComponentRoutine GetComponentRoutine(short selector)
  162. {
  163.     void     *theRtn;
  164.  
  165.     if (selector < 0)
  166.         switch (selector)                                    // standard component selectors
  167.         {
  168.             case kComponentRegisterSelect:
  169.                 theRtn = __ComponentRegister;
  170.                 break;
  171.  
  172.             case kComponentVersionSelect:
  173.                 theRtn = __ComponentVersion;
  174.                 break;
  175.  
  176.             case kComponentCanDoSelect:
  177.                 theRtn = __ComponentCanDo;
  178.                 break;
  179.  
  180.             case kComponentCloseSelect:
  181.                 theRtn = __ComponentClose;
  182.                 break;
  183.  
  184.             case kComponentOpenSelect:
  185.                 theRtn = __ComponentOpen;
  186.                 break;
  187.  
  188.             default:
  189.                 theRtn = nil;                                // unknown selector, so fail
  190.                 break;
  191.         }
  192.     else if (selector < kDelegatedSoundComponentSelectors)    // selectors that cannot be delegated
  193.         switch (selector)
  194.         {
  195.             case kSoundComponentSetSourceSelect:
  196.                 theRtn = __SetSource;
  197.                 break;
  198.  
  199.             case kSoundComponentGetSourceDataSelect:
  200.                 theRtn = __GetSourceData;
  201.                 break;
  202.  
  203.             case kSoundComponentSetOutputSelect:
  204.                 theRtn = __SetOutput;
  205.                 break;
  206.  
  207.             default:
  208.                 theRtn = nil;                                // unknown selector, so fail
  209.                 break;
  210.         }
  211.     else                                                    // selectors that can be delegated
  212.         switch (selector)
  213.         {
  214.             case kSoundComponentGetInfoSelect:
  215.                 theRtn = __GetInfo;
  216.                 break;
  217.  
  218.             case kSoundComponentStopSourceSelect:
  219.                 theRtn = __StopSource;
  220.                 break;
  221.  
  222.             case kSoundComponentPlaySourceBufferSelect:
  223.                 theRtn = __PlaySourceBuffer;
  224.                 break;
  225.  
  226.             default:
  227.                 theRtn = kDelegateComponentCall;            // unknown selector, so delegate it
  228.                 break;
  229.         }
  230.  
  231.     return (theRtn);
  232. }
  233.  
  234.  
  235. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  236. // Component Manager Methods
  237. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  238.  
  239.  
  240. /*    ==============================================================================
  241.     Component Register
  242.  
  243.     This routine is called once, usually at boot time, when the Component Manager
  244.     is first registering this sound component. This routine should check to see if the proper
  245.     Sound Manager is installed and return 0 if it is. If the right Sound Manager is not
  246.     installed, the routine should return 1 and this component will not be registered.
  247.  
  248.     NOTE: The cmpWantsRegisterMessage bit must be set in the component flags of the
  249.     sound component in order for this routine to be called.
  250.     NOTE: This routine is never called at interrupt time.
  251.     ============================================================================== */
  252.  
  253. pascal ComponentResult __ComponentRegister(void *unused1)
  254. {
  255. #pragma unused (unused1)
  256.  
  257.     long        result;
  258.     NumVersion    version;
  259.  
  260.     if ((Gestalt(gestaltSoundAttr, &result) == noErr) &&        // snd gestalt is available
  261.         (result & (1L << gestaltSoundIOMgrPresent)))            // snd dispatcher is available
  262.     {
  263.         version = SndSoundManagerVersion();                        // get the Sound Manager version
  264.         if (version.majorRev >= kRequiredSndMgrMajorRev)        // it's what we need
  265.         {
  266.             return (0);                                            // install this decompression component
  267.         }
  268.     }
  269.     
  270.     return (1);                                                    // do not install component
  271. }
  272.  
  273. /*    ==============================================================================
  274.     Component Version
  275.  
  276.     This routine is called to determine the current version of the decompression component.
  277.     It should return a fixed-point value containing the version, like 0x10001
  278.     for version 1.1. The version given here must match the version stored in
  279.     the 'thng' resource.
  280.  
  281.     NOTE: This routine is never called at interrupt time.
  282.     ============================================================================== */
  283.  
  284. pascal ComponentResult __ComponentVersion(void *unused1)
  285. {
  286. #pragma unused (unused1)
  287.  
  288.     return (kMewLawVersion);                                // return sound component version
  289. }
  290.  
  291. /*    ==============================================================================
  292.     Component CanDo
  293.  
  294.     This routine is called to determine if a particular selector is implemented.
  295.     It should return 1 if this is a valid selector, or 0 if the selector is not
  296.     implemented or if the selector is always delegated.
  297.  
  298.     NOTE: This routine is never called at interrupt time.
  299.     ============================================================================== */
  300.  
  301. pascal ComponentResult __ComponentCanDo(void *unused1, short selector)
  302. {
  303. #pragma unused (unused1)
  304.  
  305.     ComponentRoutine    theRtn;
  306.  
  307.     theRtn = GetComponentRoutine(selector);                        // see if this selector is implemented
  308.  
  309.     if ((theRtn == nil) ||                                        // selector is not implemented
  310.         (theRtn == kDelegateComponentCall))                        // or selector is always delegated
  311.         return (0);                                                // no can do
  312.     else
  313.         return (1);                                                // selector is implemented
  314. }
  315.  
  316. /*    ==============================================================================
  317.     Component Open
  318.  
  319.     This routine is called when the Component Manager creates an instance of this
  320.     component. The routine should allocate global variables in the appropriate heap
  321.     and call SetComponentInstanceStorage() so the Component Manager can remember
  322.     the globals and pass them to all the method calls.
  323.     
  324.     Determining the heap to use can be tricky. The Component Manager will normally
  325.     load the component code into the system heap, which is good, since many applications
  326.     will be sharing this component to play sound. In this case, the components's global
  327.     variable storage should also be created in the system heap.
  328.  
  329.     However, if system heap memory is tight, the Component Manager will load
  330.     the component into the application heap of the first application that plays sound.
  331.     When this happens, the component should create global storage in the application heap
  332.     instead. The Sound Manager will make sure that other applications will not try
  333.     to play sound while the component is in this application heap.
  334.  
  335.     To determine the proper heap to use, call GetComponentInstanceA5(). If the value
  336.     returned is 0, then the component was loaded into the system heap, and all storage
  337.     should be allocated there. If the value returned is non-zero, the component is in
  338.     the application heap specifed by returned A5 value, and all storage should be
  339.     allocated in this application heap.
  340.     
  341.     NOTE: If the component is loaded into the application heap, the value returned by
  342.     GetComponentRefCon() will be 0.
  343.     NOTE: Do not attempt to initialize in this call, since the Component Manager will
  344.     call Open() BEFORE calling Register().
  345.     NOTE: This routine is never called at interrupt time.
  346.     ============================================================================== */
  347.  
  348. pascal ComponentResult __ComponentOpen(void *unused1, ComponentInstance self)
  349. {
  350. #pragma unused (unused1)
  351.  
  352.     Handle            h;
  353.     GlobalsPtr        globals;
  354.  
  355.     h = NewHandleClear(sizeof(GlobalsRecord));                // get space for globals
  356.     if (h == nil)
  357.         return(MemError());
  358.  
  359.     HLock(h);
  360.     globals = (GlobalsPtr) *h;
  361.     SetComponentInstanceStorage (self, (Handle) globals);     // save pointer to our globals
  362.  
  363.     globals->globalsHandle = h;                                // remember the handle
  364.     globals->thisComponent.format = kOutputSampleFormat;    // output sample format
  365.     globals->thisComponent.sampleSize = kOutputSampleSize;    // output sample size
  366.     globals->outputSamples = kMaxOutputSamples;                // size of our output buffer
  367.  
  368.     return (noErr);
  369. }
  370.  
  371. /*    ==============================================================================
  372.     Component Close
  373.  
  374.     This routine is called when the Component Manager is closing the instance of
  375.     this component. It should delete all global storage and close any other components
  376.     that were opened.
  377.     
  378.     NOTE: Be sure to check that the globals pointer passed in to this routine is
  379.     not set to NIL. If the Open() routine fails for any reason, the Component
  380.     Manager will call this routine passing in a NIL for the globals.
  381.     NOTE: This routine is never called at interrupt time.
  382.     ============================================================================== */
  383.  
  384. pascal ComponentResult __ComponentClose(GlobalsPtr globals, ComponentInstance self)
  385. {
  386. #pragma unused (self)
  387.  
  388.     if (globals)                                            // we have some globals
  389.     {
  390.         if (globals->sourceComponent)                        // we have a source component
  391.             CloseComponent(globals->sourceComponent);        // close it
  392.     
  393.         globals->thisComponent.sampleCount = 0;                // nothing in our buffer now
  394.         DisposeHandle(globals->globalsHandle);                // dispose our storage
  395.     }
  396.  
  397.     return (noErr);
  398. }
  399.  
  400.  
  401. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  402. // Standard Decompression Component Methods
  403. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  404.  
  405. /*    ==============================================================================
  406.     SetSource
  407.  
  408.     This routine sets the component we should call to get more data. We must remember
  409.     this component and also tell it the data format of our component requires.
  410.     ============================================================================== */
  411.  
  412. pascal ComponentResult __SetSource(GlobalsPtr globals, SoundSource sourceID, ComponentInstance source)
  413. {
  414. #pragma unused (sourceID)
  415.  
  416.     SoundComponentDataPtr    sourceSifter;
  417.  
  418.     globals->sourceComponent = source;                        // remember our source component
  419.     globals->sourceDataPtr = nil;                            // nothing read from source yet
  420.  
  421.     // make sure we can get the source we need
  422.     return (SoundComponentSetOutput(source, &globals->thisComponent, &sourceSifter));
  423. }
  424.  
  425. /*    ==============================================================================
  426.     SetOutput
  427.  
  428.     This routine sets the data format our component should output. If we can't output
  429.     the requested format, we should return a pointer to the format we do support,
  430.     and return an error, and the Sound Manager will attempt the conversion for us.
  431.     ============================================================================== */
  432.  
  433. pascal ComponentResult __SetOutput(GlobalsPtr globals, SoundComponentDataPtr requested, SoundComponentDataPtr *actual)
  434. {
  435.     globals->outputSamples = requested->sampleCount;        // no. samples to output
  436.     if (globals->outputSamples > kMaxOutputSamples)            // too much for our buffer
  437.         globals->outputSamples = kMaxOutputSamples;            // only output what we can
  438.  
  439.     // make sure data format and sample sizes match
  440.  
  441.     if ((requested->format == kOutputSampleFormat) &&        // formats match
  442.         (requested->sampleSize == kOutputSampleSize))        // sample sizes match
  443.     {
  444.         return (noErr);                                        // no problem outputting this format
  445.     }
  446.     else
  447.     {
  448.         // If we can't output the requested format, the Sound Manager will make an attempt to convert our
  449.         // format into something that can be used. In order for the Sound Manager to do this, we need to
  450.         // tell it here the format we will be outputting, so it can setup the proper conversion. This is really
  451.         // handy if your algorithm only outputs 16-bit data, but the Sound Manager is requesting 8-bit. In this
  452.         // case, the Sound Manager will automatically convert your 16-bit data to 8-bit. 
  453.     
  454.         *actual = &globals->thisComponent;                    // tell the Sound Manager what we will output
  455.         return (paramErr);                                    // force the Sound Manager to convert for us
  456.     }
  457. }
  458.  
  459. /*    ==============================================================================
  460.     GetInfo
  461.  
  462.     This routine returns information about this output component to the Sound Manager.
  463.     A 4-byte OSType selector is used to determine the type and size of the information
  464.     to return. If the component does not support a selector, it should delegate this
  465.     call on up the chain.
  466.  
  467.     NOTE: This can be called at interrupt time. However, selectors that return
  468.     a handle will not be called at interrupt time.
  469.     ============================================================================== */
  470.  
  471. pascal ComponentResult __GetInfo(GlobalsPtr globals, SoundSource sourceID,
  472.                                  OSType selector, void *infoPtr)
  473. {
  474.     ComponentResult        result = noErr;
  475.  
  476.     switch (selector)
  477.     {
  478.         case siCompressionFactor:
  479.             GetCompressorInfo(infoPtr);                    // fill out the CompressionInfo structure passed in
  480.             break;
  481.  
  482.         default:
  483.             result = SoundComponentGetInfo(globals->sourceComponent, sourceID, selector, infoPtr);
  484.             break;
  485.     }
  486.  
  487.     return (result);
  488. }
  489.  
  490. /*    ==============================================================================
  491.     StopSource
  492.  
  493.     This routine is used to stop sounds that are currently playing. It should
  494.     clear out any internal buffers, reset any decompression state information
  495.     and then delegate the call up the chain.
  496.  
  497.     NOTE: This can be called at interrupt time.
  498.     ============================================================================== */
  499.  
  500. pascal ComponentResult __StopSource(GlobalsPtr globals, short count, SoundSource *sources)
  501. {
  502.     globals->sourceDataPtr = nil;                        // clear out internal buffers
  503.     globals->thisComponent.sampleCount = 0;                // our buffer is empty
  504.     InitializeDecompressor(globals);                    // initialize our decompressor state
  505.  
  506.     return (SoundComponentStopSource(globals->sourceComponent, count, sources));    // delegate this call
  507. }
  508.  
  509. /*    ==============================================================================
  510.     PlaySourceBuffer
  511.  
  512.     This routine is used to start a new sound playing. It should clear out any internal buffers
  513.     but should NOT reset any decompression state information, since this could be a
  514.     continuation of a sound that has been broken into pieces. Then the call should be
  515.     delegated up the chain.
  516.  
  517.     NOTE: This can be called at interrupt time.
  518.     ============================================================================== */
  519.  
  520. pascal ComponentResult __PlaySourceBuffer(GlobalsPtr globals, SoundSource sourceID, SoundParamBlockPtr pb, long actions)
  521. {
  522.     globals->sourceDataPtr = nil;                        // clear out internal buffers
  523.     globals->thisComponent.sampleCount = 0;                // our buffer is empty
  524.  
  525.     return (SoundComponentPlaySourceBuffer(globals->sourceComponent, sourceID, pb, actions));    // delegate this call
  526. }
  527.  
  528. /*    ==============================================================================
  529.     GetSourceData
  530.  
  531.     This routine is called when the Sound Manager wants your component to decompress
  532.     some more data. It should first make sure it has some source data, then
  533.     decompress into an internal buffer and return that buffer to the Sound Manager.
  534.     If the Sound Manager is requesting the data in reverse, you must decompress
  535.     the data starting from the end of the source buffer, and the Sound Manager will
  536.     reverse the samples for you.
  537.  
  538.     NOTE: This will most often be called at interrupt time.
  539.     ============================================================================== */
  540.  
  541. pascal ComponentResult __GetSourceData(GlobalsPtr globals, SoundComponentDataPtr *resultDataPtr)
  542. {
  543.     SoundComponentDataPtr    sourceDataPtr;
  544.     unsigned long            samplesConverted, framesToConvert, bytesToSkip;
  545.     ComponentResult            result;
  546.     Byte                    *inputBuffer;
  547.  
  548.     result = noErr;
  549.     sourceDataPtr = globals->sourceDataPtr;                    // get pointer to source sound component
  550.  
  551.     if (sourceDataPtr == nil)                                // source buffer was flushed
  552.     {
  553.         result = PrimeSource(globals);                        // start with all new source data
  554.     }
  555.     else if (sourceDataPtr->sampleCount == 0)                // source buffer is empty
  556.     {
  557.         result = SoundComponentGetSourceData(globals->sourceComponent, &globals->sourceDataPtr); // fill it up                    // continue where we left off
  558.     }
  559.  
  560.     if (result != noErr)                                    // bail if error
  561.         return (result);
  562.  
  563.     sourceDataPtr = globals->sourceDataPtr;                    // get pointer to source sound component
  564.  
  565.     if ((sourceDataPtr->format == globals->thisComponent.format) ||    // input and output are same
  566.         (sourceDataPtr->buffer == nil))                        // or no source buffer
  567.     {
  568.         globals->sourceDataPtr = nil;                        // get new source next time
  569.         *resultDataPtr = sourceDataPtr;                        // pass source on down
  570.     }
  571.     else
  572.     {
  573.         // convert the source samples into frames
  574.         framesToConvert = sourceDataPtr->sampleCount / globals->compInfo.samplesPerPacket;
  575.  
  576.         if (framesToConvert)                                // source has some data for us
  577.         {
  578.             if (framesToConvert > globals->outputFrames)
  579.                 framesToConvert = globals->outputFrames;    // limited to size of output
  580.  
  581.             // convert frames back into samples to quantize the source correctly
  582.             samplesConverted = framesToConvert * globals->compInfo.samplesPerPacket;
  583.  
  584.             // If the Sound Manager is going to play this sound backwards, we need to decompress
  585.             // starting from the end of the buffer, and it will reverse the decompressed samples for us.
  586.  
  587.             inputBuffer = sourceDataPtr->buffer;            // point at input buffer
  588.             if (globals->reverse)
  589.             {
  590.                 bytesToSkip = sourceDataPtr->sampleCount - samplesConverted;    // no. samples to skip
  591.                 bytesToSkip = (bytesToSkip / globals->compInfo.samplesPerPacket) * globals->compInfo.bytesPerFrame; // convert samples into bytes
  592.                 inputBuffer += bytesToSkip;                    // decompress from end of buffer
  593.             }
  594.  
  595.             // If it is playing forward (the normal case), we just skip over the source samples that
  596.             // will be decompressed below.
  597.  
  598.             else
  599.             {
  600.                 bytesToSkip = (samplesConverted / globals->compInfo.samplesPerPacket) * globals->compInfo.bytesPerFrame;
  601.                 sourceDataPtr->buffer += bytesToSkip;        // skip over the source consumed
  602.             }
  603.  
  604.             sourceDataPtr->sampleCount -= samplesConverted;    // this many samples will be decompressed
  605.  
  606.             // Do the decompression
  607.  
  608.             if (sourceDataPtr->numChannels == 1)            // mono - decompress right into output buffer
  609.             {
  610.                 DecompressULaw(inputBuffer, globals->buffer, framesToConvert, 1, 1);
  611.             }
  612.             else                                            // stereo - decompress each channel separately
  613.             {
  614.                 // do the left samples
  615.                 DecompressULaw(inputBuffer, globals->buffer, framesToConvert, 2, 1);
  616.  
  617.                 // do the right samples
  618.                 DecompressULaw(inputBuffer, globals->buffer, framesToConvert, 2, 2);
  619.             }
  620.         }
  621.         else
  622.             samplesConverted = 0;                            // no samples were converted
  623.  
  624.         globals->thisComponent.buffer = (Byte *) globals->buffer;    // data in this buffer
  625.         globals->thisComponent.sampleCount = samplesConverted;        // return num. samples converted
  626.  
  627.         *resultDataPtr = &globals->thisComponent;            // return description of decompressed data
  628.     }
  629.  
  630.     return (result);
  631. }
  632.  
  633. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  634. // This routine is used to prime the source. It gets the first load of data
  635. // from the source and intializes the output format and compression factors.
  636.  
  637. ComponentResult PrimeSource(GlobalsPtr globals)
  638. {
  639.     ComponentResult            result;
  640.     SoundComponentDataPtr    sourceDataPtr;
  641.  
  642.     // get data from source
  643.  
  644.     result = SoundComponentGetSourceData(globals->sourceComponent, &globals->sourceDataPtr);
  645.     if (result != noErr)
  646.         return (result);
  647.     if (globals->sourceDataPtr == nil)
  648.         return (paramErr);
  649.  
  650.     // copy source settings so we know what to output. Notice that we do not change the sampleSize
  651.     // or format fields, since we always output 16-bit, twos-complement data in this example.
  652.  
  653.     sourceDataPtr = globals->sourceDataPtr;
  654.     globals->thisComponent.flags = sourceDataPtr->flags;                // copy flags unchanged
  655.     globals->thisComponent.sampleRate = sourceDataPtr->sampleRate;        // copy sample rate unchanged
  656.     globals->thisComponent.numChannels = sourceDataPtr->numChannels;    // copy numchannels unchanged
  657.  
  658.     // The Sound Manager sets the flags field of the sourceDataPtr to indicate if the
  659.     // sound should be played backwards. If this bit is set, we just store it in the
  660.     // globals so we know to decompress from the end of the buffer.
  661.  
  662.     if (sourceDataPtr->flags & kReverse)                                // source is to be played backwards
  663.         globals->reverse = true;
  664.     else
  665.         globals->reverse = false;
  666.  
  667.     // Setup the the compression info, so that we can convert between samples, frames and bytes correctly.
  668.  
  669.     globals->compInfo.recordSize = sizeof(CompressionInfo);
  670.     globals->compInfo.format = sourceDataPtr->format;
  671.     GetCompressorInfo(&globals->compInfo);                    // get compression info
  672.     globals->compInfo.bytesPerFrame = globals->compInfo.bytesPerPacket * sourceDataPtr->numChannels;
  673.  
  674.     globals->outputFrames = globals->outputSamples / globals->compInfo.samplesPerPacket;
  675.  
  676.     return (noErr);
  677. }
  678.  
  679. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  680. // Compressor-specific Methods
  681. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  682.  
  683. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  684. // This routine initializes the decompressor.
  685.  
  686. void InitializeDecompressor(GlobalsPtr globals)                // initialize our decompressor state
  687. {
  688. #pragma unused (globals)
  689.  
  690.     // Here you should initialize any state used by your decompression alorithm (such as predictors)
  691.     // to default values. This routine will be called whenever a new sound is started so you can set
  692.     // up correctly. In our example, we do not have any state, so we have nothing to set up.
  693. }
  694.  
  695. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  696. // This routine returns information about the compression ratios.
  697.  
  698. void GetCompressorInfo(CompressionInfoPtr cp)
  699. {
  700.     if (cp->recordSize > sizeof(CompressionInfo))            // limit amount we return
  701.         cp->recordSize = sizeof(CompressionInfo);
  702.  
  703.     cp->compressionID = fixedCompression;                    // must set this to fixedCompression
  704.     cp->samplesPerPacket = 1;                                // no. samples in one compressed packet
  705.     cp->bytesPerPacket = 1;                                    // no. bytes in a packet
  706.     cp->bytesPerSample = 2;                                    // no. bytes in a decompressed sample
  707. }
  708.  
  709. /*    This example uses uLaw encoding.
  710.  
  711.     In uLaw, 14-bits of linear sampling is reduced to 8 bits of logarithmic data.
  712.     It is used on North American and Japanese phone systems, and is coming into use
  713.     for voice data interchange, for PBXs, voicemail, MIME (Internet standard for multimedia mail),
  714.     and Internet Talk Radio. µLaw sounds are almost always encoded at 8000, 8012, or 8012.8210513
  715.     samples/sec. 8000 because it is the specified standard for phones, and 8012.8210513
  716.     (and rounded to 8012) because it is apparently the actual rate used in domestic digital phone switches.
  717.  
  718.     ---------------------------
  719.     U-LAW and A-LAW definitions
  720.     ---------------------------
  721.     
  722.     [Adapted from information provided by duggan@cc.gatech.edu (Rick
  723.     Duggan) and davep@zenobia.phys.unsw.EDU.AU (David Perry)]
  724.     
  725.     u-LAW (really mu-LAW) is
  726.     
  727.               sgn(m)   (     |m |)       |m |
  728.        y=    ------- ln( 1+ u|--|)       |--| =< 1
  729.              ln(1+u)   (     |mp|)       |mp|         
  730.     
  731.     A-LAW is
  732.     
  733.          |     A    (m )                 |m |    1
  734.          |  ------- (--)                 |--| =< - 
  735.          |  1+ln A  (mp)                 |mp|    A     
  736.        y=|
  737.          | sgn(m) (        |m |)    1    |m |
  738.          | ------ ( 1+ ln A|--|)    - =< |--| =< 1
  739.          | 1+ln A (        |mp|)    A    |mp|         
  740.  
  741.     Values of u=100 and 255, A=87.6, mp is the Peak message value, m is the current quantised message value.
  742.     (The formulae get simpler if you substitute x for m/mp and sgn(x) for sgn(m); then -1 <= x <= 1.)
  743.  
  744.     Converting from u-LAW to A-LAW is in a sense "lossy" since there are quantizing errors introduced in
  745.     the conversion.
  746.  
  747.     "..the u-LAW used in North America and Japan, and the A-LAW used in Europe and the rest of the world
  748.     and international routes.."
  749.  
  750.     References:
  751.     
  752.     Modern Digital and Analog Communication Systems, B.P.Lathi., 2nd ed. ISBN 0-03-027933-X
  753.     
  754.     Transmission Systems for Communications
  755.     Fifth Edition
  756.     by Members of the Technical Staff at Bell Telephone Laboratories
  757.     Bell Telephone Laboratories, Incorporated
  758.     Copyright 1959, 1964, 1970, 1982
  759. */
  760.  
  761. /*
  762. ** This routine converts from ulaw to 16 bit linear. The really fast way to do this is
  763. ** with a table, but this is left as an exercise for the reader.
  764. **
  765. ** Craig Reese: IDA/Supercomputing Research Center
  766. ** 29 September 1989
  767. **
  768. ** References:
  769. ** 1) CCITT Recommendation G.711  (very difficult to follow)
  770. ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
  771. **     for Analog-to_Digital Conversion Techniques,"
  772. **     17 February 1987
  773. **
  774. ** Input: 8 bit ulaw sample
  775. ** Output: signed 16 bit linear sample
  776. */
  777.  
  778. void DecompressULaw(Byte *inbuf, short *outbuf, unsigned long framesToConvert,
  779.                     unsigned long numChannels, unsigned long whichChannel)
  780. {
  781.     const int        exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
  782.     unsigned char    ulawbyte;
  783.     int                i, sign, exponent, mantissa, sample;
  784.  
  785.     whichChannel--;
  786.     inbuf += whichChannel;
  787.     outbuf += whichChannel;
  788.  
  789.     for (i = 0; i < framesToConvert; i++)                    // loop over all source frames
  790.     {
  791.         ulawbyte = *inbuf;                                    // get µLaw sample
  792.         inbuf += numChannels;
  793.  
  794.         ulawbyte = ~ulawbyte;                                // convert µLaw sample to 16-bit linear sample
  795.         sign = (ulawbyte & 0x80);
  796.         exponent = (ulawbyte >> 4) & 0x07;
  797.         mantissa = ulawbyte & 0x0F;
  798.         sample = exp_lut[exponent] + (mantissa << (exponent + 3));
  799.         if (sign != 0)
  800.             sample = -sample;
  801.     
  802.         *outbuf = sample;                                    // output 16-bit sample
  803.         outbuf += numChannels;
  804.     }
  805. }
  806.